﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;

namespace Jim.Core;

/// <summary>
/// SDK基类
/// </summary>
public abstract class SdkClient : IDisposable
{
    /// <summary>
    /// Http请求客户端
    /// </summary>
    protected HttpHelper httpHelper =null;
    /// <summary>
    /// 会话
    /// </summary>
    protected CookieContainer CookieContainer = null;

    /// <summary>
    /// 服务器地址
    /// </summary>
    public string ServerUrl { get; set; }

    #region 调试   
    /// <summary>
    /// 是否调试模式
    /// </summary>
    public bool IsDebug { get; set; } = false;

    /// <summary>
    /// 记录调试信息
    /// </summary>
    /// <param name="message"></param>
    protected void Log(string message)
    {
        if (IsDebug) Debug.WriteLine(message);
    }
    #endregion


    #region 返回值 
    /// <summary>
    /// 返回失败对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="message"></param>
    /// <returns></returns>
    protected T Error<T>(string message) where T : ISdkResponse => Error<T>("500", message);
    /// <summary>
    /// 返回失败对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="code"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    protected T Error<T>(string code, string message) where T : ISdkResponse
    {
        T rsp = Activator.CreateInstance<T>();
        rsp.Code = code;
        rsp.Message = message;
        return rsp;
    }
    /// <summary>
    /// 返回成功对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    protected T Success<T>(object obj) where T : ISdkResponse => Success<T>(JToken.FromObject(obj));
    /// <summary>
    /// 返回成功对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataToken"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    protected T Success<T>(JToken dataToken, string message = "") where T : ISdkResponse
    {
        JObject newobj = new JObject();
        newobj.Add("code", "200");
        if (!string.IsNullOrWhiteSpace(message)) newobj.Add("message", message);
        if (dataToken != null) newobj.Add("result", dataToken);
        return newobj.ToObject<T>();
    }

    #endregion

    /// <summary>
    /// 执行请求
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="request"></param>
    /// <returns></returns>
    public abstract Task<T> Execute<T>(ISdkRequest<T> request) where T : ISdkResponse;

    /// <summary>
    /// 构建Header头部请求
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    protected virtual SdkDictionary BuildHeader(ISdkRequest request)
    {
        SdkDictionary headers = new SdkDictionary();
        if (request is ISdkCustomHeader customHeader)
            headers.AddAll(customHeader.Headers());
        return headers;
    }

    /// <summary>
    /// 构建请求路径
    /// </summary>
    /// <param name="request">请求对象</param>
    /// <param name="encod">参数值是否Url加密</param>
    /// <param name="customerEndUrl">Url结束</param>
    /// <returns></returns>
    protected virtual string BuildUrl(ISdkRequest request,bool encod = false,string customerEndUrl ="")
    {
        SdkAttribute attr = request.GetType().GetCustomAttribute<SdkAttribute>();
        // + (ServerUrl.EndsWith("/") ? "" : "/")

        if (attr.Url.StartsWith("/") && ServerUrl.EndsWith("/")) ServerUrl = ServerUrl.Substring(0, ServerUrl.Length - 1);
        if (! attr.Url.StartsWith("/") && !ServerUrl.EndsWith("/")) ServerUrl = ServerUrl + "/";

        string url = ServerUrl + attr.Url + (customerEndUrl.IsNullOrEmpty() ? "" : customerEndUrl);
        // 如果是Post请求，直接返回
        if (attr.Method == HttpMethod.Post) return url;
        // 如果是get请求，需要拼接请求参数
        object requestObj = request.GetRequestObject();
        url.AddQueryParam(requestObj, encod);
        return url;
    }

    /// <summary>
    /// 构建Post数据
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    protected virtual string BuildPostData(ISdkRequest request)
    {
        object requestObj = request.GetRequestObject();
        return requestObj.ToJson();
    }

    protected virtual SdkDictionary BuildPostDataDic(ISdkRequest request,bool encode = false,List<string>? excludeProps = null)
    {
        excludeProps ??= new List<string>();

        // 自定义字典类型
        if (request is ISdkCustomDic sdkDic)
        {
            return sdkDic.Dic();
        }
        // 未自定义字典类型
        SdkDictionary dic = new SdkDictionary();
        object requestObj = request.GetRequestObject();
        var properties = requestObj.GetType().GetProperties()
            .Where(p => p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length == 0);
        foreach (var property in properties)
        {
            var key = excludeProps.Find(u => u.Equals(property.Name, StringComparison.OrdinalIgnoreCase));
            if (string.IsNullOrEmpty(key)) 
                dic.Add(property.Name.ToCamelCase(), property.GetValue(requestObj));
        }
        return dic;
    }

    protected virtual byte[] BuildPostDataByte(ISdkRequest request)
    {
        object requestObj = request.GetRequestObject();
        var json =  requestObj.ToJson();
        byte[] bytes = Encoding.UTF8.GetBytes(json);
        return bytes;
    }

    /// <summary>
    /// 解析返回对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="request"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    protected abstract T BuildResponse<T>(ISdkRequest request, string value) where T : ISdkResponse;

    public void Dispose()
    {
        if (httpHelper != null) httpHelper = null;
        if (CookieContainer != null) CookieContainer = null;
    }
}